#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include "LockGuard.hpp"
#include "Thread.hpp"
#include <queue>
#include <functional>
using namespace std;

struct ThreadData {
    ThreadData (const string& threadname) 
        :_threadname(threadname)
    {
        
    }
    string _threadname;
};

const int default_num = 10;// 默认线程数量

template <class T>
class threadpool {
    public :
    threadpool(const int num = default_num) 
        :_thread_num(num)
    {
        // 初始化互斥锁和条件变量
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        // 创建指定数量的线程
        for (int i = 1; i <= _thread_num; i++) {
            string threadname = "thread" + to_string(i);
            ThreadData td(threadname);
            // thread<ThreadData> t(threadname, bind(&threadpool<T>::ThreadRun, this, placeholders::_1), td);
            // lg.PrintLog(Info, "%s create sucess!", threadname.c_str());
            // _threads.push_back(t);
            _threads.emplace_back(thread<ThreadData>(threadname, bind(&threadpool<T>::ThreadRun, this, placeholders::_1), td));
            lg.PrintLog(Info, "%s create sucess!", threadname.c_str());
        }
    }

    void Push(const T& in) {
        // 先加锁
        LockGuard lock(&_mutex);
        _q.push(in);
        pthread_cond_signal(&_cond); // 唤醒一个线程
    }

    void Start() {
        for (auto& thread : _threads) {
            thread.Start();
            lg.PrintLog(Info, "%s is start!", thread.get_name().c_str());
        }
    }


    void ThreadRun(ThreadData& td) {
        T t;
        while (true) {
            {
                // 先加锁
                LockGuard lock(&_mutex);
                while (_q.empty()) {
                    pthread_cond_wait(&_cond, &_mutex);
                }
                t = _q.front();
                _q.pop();
                // 处理任务
                t();
                // sleep(1);
                lg.PrintLog(Debug, "%s handle done a task: %s, result is: %s", td._threadname.c_str(), t.TaskToString().c_str(), \
                t.ResultToString().c_str());
                // 唤醒其他线程
            }

        }
    }

    ~threadpool() {
        for (auto& thread : _threads) {
            
            thread.Join();
        }
    }



    private :
    queue<T> _q; // 任务队列
    vector<thread<ThreadData>> _threads; // 线程集合
    int _thread_num; // 线程数量
    pthread_mutex_t _mutex; // 互斥锁
    pthread_cond_t _cond; // 条件变量
};
